package com.jlf.core.engine.constant;


import org.objectweb.asm.Opcodes;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.concurrent.ConcurrentHashMap;

/**
 * schema的常量
 *
 * @author wujr
 * 2023/7/5
 * @version 1.0
 * 【变更历史】
 * [wujr 2023/7/5 1.0 新增]
 */
public interface SchemaConstant {
    interface Domain{
        interface Status{
            /**
             * 已经生效
             */
            Integer valid = 1;
        }
        interface Index{
            Integer index = 1;
            Integer unique = 2;
        }
    }
    interface Jdbc {
        interface Criterion{
            Integer eq = 1;
            Integer ne = 2;
            Integer like = 3;
            Integer notLike = 4;
            Integer gt = 5;
            Integer ge = 6;
            Integer lt = 7;
            Integer le = 8;
            Integer likeLeft = 9;
            Integer likeRight = 10;
            Integer notLikeLeft = 11;
            Integer notLikeRight = 12;

            Integer mask = eq | (1 << (ne - 1)) | (1 << (like - 1)) |
                    (1 << (notLike - 1)) | (1 << (gt - 1)) |
                    (1 << (ge - 1)) | (1 << (lt - 1)) | (1 << (le - 1)) |
                    (1 << (likeLeft - 1)) | (1 << (likeRight - 1)) |
                    (1 << (notLikeLeft - 1)) | (1 << (notLikeRight - 1));
        }
        interface Transaction{
            Integer add = 1;
            Integer edit = 2;
            Integer delete = 3;
        }
        interface id{
            Integer none = 0;
            /**
             * 手动输入
             */
            Integer input = 1;
            /**
             * 自增id
             */
            Integer auto = 2;
            /**
             * 雪花算法的分布式id
             */
            Integer snow = 3;
        }
        static boolean isAutoIncrement(Integer idType){
            return id.auto.equals(idType);
        }
        static boolean isTypeAllowAlter(int originalType, int recentType){
            if (originalType >= Type.SHORT && originalType <= Type.BIGINT){
                // 这是整数，key转换为：浮点，字符串
                if (recentType >= Type.FLOAT && recentType <= Type.DOUBLE){
                    return true;
                }else if (recentType >= Type.STRING && recentType <= Type.CLOB){
                    return true;
                }else if (recentType >= Type.SHORT && recentType <= Type.BIGINT){
                    return originalType < recentType;
                }else{
                    // 其它类型，不支撑
                    return false;
                }
            }else if (Type.FLOAT.equals(originalType) && Type.DOUBLE.equals(recentType)){
                return true;
            }else if (Type.DECIMAL.equals(originalType) && Type.DOUBLE.equals(recentType)){
                return true;
            }else if (Type.BOOLEAN.equals(originalType)){
                return recentType >= Type.SHORT && recentType <= Type.BIGINT;
            }else if (Type.STRING.equals(originalType) && Type.CLOB.equals(recentType)){
                return true;
            }else if (Type.DATE.equals(originalType) && (Type.DATETIME.equals(recentType) || Type.TIMESTAMP.equals(recentType))){
                return true;
            }else{
                return false;
            }
        }
        // https://blog.csdn.net/qq_21187515/article/details/91495237
        // 定义数据库的数据类型
        interface Type{
            int MIN = 2;
            Integer SHORT = 2;
            Integer INTEGER = 3;
            Integer BIGINT = 4;
            Integer FLOAT = 5;
            Integer DOUBLE = 6;
            Integer DECIMAL = 7;
            Integer BOOLEAN = 8;
            Integer STRING = 9;
            Integer CLOB = 10;
            Integer BLOB = 11;
            Integer DATE = 12;
            Integer TIME = 13;
            Integer DATETIME = 14;
            Integer TIMESTAMP = 15;
            int MAX = 15;
        }
    }
    interface Java{
        interface Type{
            int MIN = -1;
            /**
             * String
             */
            Integer STRING = 0;
            /**
             * Boolean  boolean
             */
            Integer BOOL = 1;
            /**
             * Byte byte
             */
            Integer BYTE = 2;
            /**
             * Short short
             */
            Integer SHORT = 3;
            /**
             * Integer int
             */
            Integer INTEGER = 4;
            /**
             * Long long
             */
            Integer LONG = 5;
            /**
             * BigInteger
             */
            Integer BIGINT = 6;
            /**
             * Float float
             */
            Integer FLOAT = 7;
            /**
             * Double double
             */
            Integer DOUBLE = 8;
            /**
             * BigDecimal
             */
            Integer DECIMAL = 9;
            /**
             * java.util.Date
             */
            Integer DATE = 10;
            /**
             * java.util.Date
             */
            Integer TIME = 11;
            /**
             * java.util.Timestamp
             */
            Integer TIMESTAMP = 12;
            Integer LOCAL_DATE = 13;
            Integer LOCAL_TIME = 14;
            Integer LOCAL_DATETIME = 15;
            /**
             * byte[]
             */
            Integer ARRAY = 16;
            /**
             * 对象
             */
            Integer OBJECT = -1;
            int MAX = 16;
        }
        static Class<?> type(Integer type){
            return mapJavaType.get(type);
        }
        static boolean isPrimitive(Integer type){
            return Type.BOOL.equals(type) ||
                    Type.BYTE.equals(type) ||
                    Type.SHORT.equals(type) ||
                    Type.INTEGER.equals(type) ||
                    Type.LONG.equals(type) ||
                    Type.FLOAT.equals(type) ||
                    Type.DOUBLE.equals(type);
        }
        static String asmType(Class<?> clz){
            if (Boolean.class.equals(clz) || boolean.class.equals(clz)){
                return org.objectweb.asm.Type.getDescriptor(Boolean.TYPE);
            }else if (Byte.class.equals(clz) || byte.class.equals(clz)){
                return org.objectweb.asm.Type.getDescriptor(Byte.TYPE);
            }else if (Short.class.equals(clz) || short.class.equals(clz)){
                return org.objectweb.asm.Type.getDescriptor(Short.TYPE);
            }else if (Integer.class.equals(clz) || int.class.equals(clz)){
                return org.objectweb.asm.Type.getDescriptor(Integer.TYPE);
            }else if (Long.class.equals(clz) || long.class.equals(clz)){
                return org.objectweb.asm.Type.getDescriptor(Long.TYPE);
            }else if (Float.class.equals(clz) || float.class.equals(clz)){
                return org.objectweb.asm.Type.getDescriptor(Float.TYPE);
            }else if (Double.class.equals(clz) || double.class.equals(clz)){
                return org.objectweb.asm.Type.getDescriptor(Byte.TYPE);
            }else{
                return org.objectweb.asm.Type.getDescriptor(clz);
            }
        }
        static int asmLoad(Integer type){
            Integer mode = mapJavaAsmLoad.get(type);
            return mode == null ? Opcodes.ALOAD : mode;
        }
        static int asmStore(Integer type){
            Integer mode = mapJavaAsmStore.get(type);
            return mode == null ? Opcodes.ASTORE : mode;
        }
        static int asmConst(Integer type){
            Integer mode = mapJavaAsmConst.get(type);
            return mode == null ? Opcodes.ACONST_NULL : mode;
        }

        static boolean isString(Integer type){
            return Type.STRING.equals(type);
        }
    }
    ConcurrentHashMap<Integer, Integer> mapJavaAsmConst = new ConcurrentHashMap<>(){{
        put(Java.Type.BOOL, Opcodes.BIPUSH);
        put(Java.Type.BYTE, Opcodes.BIPUSH);
        put(Java.Type.SHORT, Opcodes.SIPUSH);
        put(Java.Type.INTEGER, Opcodes.ICONST_0);
        put(Java.Type.LONG, Opcodes.LCONST_0);
        put(Java.Type.FLOAT, Opcodes.FCONST_0);
        put(Java.Type.DOUBLE, Opcodes.DCONST_0);
    }};
    ConcurrentHashMap<Integer, Integer> mapJavaAsmLoad = new ConcurrentHashMap<>(){{
        put(Java.Type.BOOL, Opcodes.ILOAD);
        put(Java.Type.BYTE, Opcodes.ILOAD);
        put(Java.Type.SHORT, Opcodes.ILOAD);
        put(Java.Type.INTEGER, Opcodes.ILOAD);
        put(Java.Type.LONG, Opcodes.LLOAD);
        put(Java.Type.FLOAT, Opcodes.FLOAD);
        put(Java.Type.DOUBLE, Opcodes.DLOAD);
    }};
    ConcurrentHashMap<Integer, Integer> mapJavaAsmStore = new ConcurrentHashMap<>(){{
        put(Java.Type.BOOL, Opcodes.ISTORE);
        put(Java.Type.BYTE, Opcodes.ISTORE);
        put(Java.Type.SHORT, Opcodes.ISTORE);
        put(Java.Type.INTEGER, Opcodes.ISTORE);
        put(Java.Type.LONG, Opcodes.LSTORE);
        put(Java.Type.FLOAT, Opcodes.FSTORE);
        put(Java.Type.DOUBLE, Opcodes.DSTORE);
    }};

    ConcurrentHashMap<Integer, Class<?>> mapJavaType = new ConcurrentHashMap<>(){{
        put(Java.Type.STRING, String.class);
        put(Java.Type.BOOL, Boolean.class);
        put(Java.Type.BYTE, Byte.class);
        put(Java.Type.SHORT, Short.class);
        put(Java.Type.INTEGER, Integer.class);
        put(Java.Type.LONG, Long.class);
        put(Java.Type.BIGINT, BigInteger.class);
        put(Java.Type.FLOAT, Float.class);
        put(Java.Type.DOUBLE, Double.class);
        put(Java.Type.DECIMAL, BigDecimal.class);
        put(Java.Type.DATE, java.util.Date.class);
        put(Java.Type.TIME, java.util.Date.class);
        put(Java.Type.TIMESTAMP, java.util.Date.class);
        put(Java.Type.LOCAL_DATE, java.time.LocalDate.class);
        put(Java.Type.LOCAL_TIME, java.time.LocalTime.class);
        put(Java.Type.LOCAL_DATETIME, java.time.LocalDateTime.class);
        put(Java.Type.ARRAY, Byte[].class);
    }};
}
